#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include "card.h"
using namespace std;

//+-------------------------------------------------------------+
//| Card::Card()                                                |
//+-------------------------------------------------------------+
//| Description:                                                |
//| Constructor for a playing card.                             |
//| Checks that the value is in the range 1..54 and then...     |
//+-------------------------------------------------------------+
Card::Card(int value,State state) 
: value_(value)
, state_(state)
{
	//value should bigger than 0

	if(value>=redJoker)
	{
		suit_=trump;
		suitValue_=redJoker;
	}
	else
	{
		if(value==blackJoker)
		{
			suit_=trump;
			suitValue_=blackJoker;
		}
		else
		{ 
			switch( (value-1)/13 )
			{
			case 0:
				suit_=diamonds;
				suitValue_=(value-1)%13+1;
				break;
			case 1:
				suit_=clubs;
				suitValue_=(value-1)%13+1;
				break;
			case 2:
				suit_=hearts ;
				suitValue_=(value-1)%13+1;
				break;
			case 3:
				suit_=spades ;
				suitValue_=(value-1)%13+1;
				break;
			}
		}
	}
	
} // Card::Card()

void Card::show()
{
	switch(suit_)
	{
	case diamonds :
		print("diamonds");
		break;
	case clubs:
		print("clubs");
		break;
	case hearts:
		print("hearts");
		break;
	case spades:
		print("spades");
		break;
	case trump:
		print("trump");
		break;
	}
}

void Card::print(const char* suitname)
{
	switch(suitValue_)
	{
	case 11:
		printf("%s-%c\n", suitname, 'J');
		break;
	case 12:
		printf("%s-%c\n", suitname, 'Q');
		break;
	case 13:
		printf("%s-%c\n", suitname, 'K');
		break;
	case blackJoker:
		printf("%s-%s\n", suitname, "blackJoker");
		break;
	case redJoker:
		printf("%s-%s\n", suitname, "redJoker");
		break;
	default:
		printf("%s-%d\n", suitname, suitValue_);
		break;
	}
}



Pack::~Pack()
{
	vector<Card*>::iterator iter=pack_.begin();
	for(; iter!=pack_.end(); ++iter)
		delete *iter;
}

void Pack::init()
{
	pack_.clear();
	for(int i=1; i<55; i++)
	{
		Card* card=new Card(i,inpool);
		pack_.push_back(card);
	}
}
void Pack::init(int number)
{
	pack_.clear();
	for(int i=1; i<number; i++)
	{
		Card* card=new Card(i,inpool);
		pack_.push_back(card);
	}
}

class Random //for random_shuffle
{
public:
	Random()
	{
		if ( !seeded )
		{
			srand( time( 0 ) );
			seeded = true;
		}
	}
	int operator()( int n ){return rand() % n;}
public:
	static bool seeded;
};
bool Random::seeded = false;

void Pack::shuffle()
{
	random_shuffle(pack_.begin(),pack_.end(), Random());
}


bool Pack::deal(int count, vector<Card*>& cardList)
{
	cardList.clear();
	for(int i=0;i<count;i++)
	{
		Card* pcard=dealOne();
		if(pcard==NULL)
			return false;
		cardList.push_back(pcard);
	}
	return true;
}

Card* Pack::dealOne()
{
	vector<Card*>::iterator iter=pack_.begin();
	for(; iter!=pack_.end(); ++iter)
	{
		if((*iter)->getState()!=inpool)
			continue;
		else
		{
			(*iter)->setState(userhand);
			return *iter;
		}
	}
	return NULL;
}

Card* Pack::draw(int index)
{
	vector<Card*>::iterator iter=pack_.begin();
	for(int i=1; iter!=pack_.end(); ++iter)
	{
		if( (*iter)->getState()!=inpool )
			continue;
		else
		{
			if(i==index)
			{
				(*iter)->setState(userhand);
				return *iter;
			}
			i++;
		}
	}
	return NULL;
}

void Pack::show()
{
	vector<Card*>::iterator iter=pack_.begin();
	for(; iter!=pack_.end(); ++iter)
		(*iter)->show();
}

Player::Player()
: money_(10000)
, isWin_(false)
{
}
void Player::init()
{
	//money_=10000;
	isWin_=false;
	vector<Card*>::iterator iter=hand_.begin();
	for(; iter!=hand_.end(); ++iter)
		delete *iter;
}

void Player::show()
{
	cout<<"| Cards in Hand:                                              |\n";
	vector<Card*>::iterator iter=hand_.begin();
	for(; iter!=hand_.end(); ++iter)
		(*iter)->show();
	cout<<"| Money :                                                     |\n"
		<<money_<<"\n"
		<<"+-------------------------------------------------------------+\n";

}

vector<Card*>& Player::bid()
{
	return hand_;
}

bool Player::ante(int USD)
{
	if(USD<=0)
	{
		cout<<"please ante more than 1 USD\n";
		return false;
	}
	if(USD>money_)
	{
		cout<<"you don't have enough money\n";
		return false;
	}
	money_-=USD;
	return true;
}

Game::Game()
: start_(false)
, stake_(0)
, cardCount_(0)
{
}
void Game::start()
{
	init();
	start_=true;
	startRound();
}

void Game::end()
{
	start_=false;
	cout<<" Game end~ "<<endl;	
}

void Game::startRound()
{
	stake_=0;
	cardCount_=0;
	shuffle();
	computer_.init();
	play_.init();

	computer_.bid().push_back(pk_.dealOne());
	play_.bid().push_back(pk_.dealOne());
	cardCount_++;
	computer_.bid().push_back(pk_.dealOne());
	play_.bid().push_back(pk_.dealOne());
	cardCount_++;
	show();
}
void Game::endRound()
{
	if(isWin())
	{
		play_.moneyAdd(stake_);
		cout<<"You win this round! "<<endl;
	}
	else
	{
		computer_.moneyAdd(stake_);
		cout<<"You lose this round! "<<endl;
	}

	show();
}
bool Game::isWin()
{
	if( Compare())
		play_.setWin(true);
	return play_.isWin();
}

bool Game::Compare()
{
	HandInfo playHI,computerHI;
	playHI=GetHandInfo(play_);
	computerHI=GetHandInfo(computer_);
	
	if(playHI.h_ > computerHI.h_)
		return true;
	if(playHI.h_ < computerHI.h_)
		return false;

	if(playHI.v_ ==1 && computerHI.v_!=1)
		return true;
	if(playHI.v_ > computerHI.v_)
		return true;
	else
		return false;
}
HandInfo Game::GetHandInfo(Player& p )
{
	vector<Card*>& hcards=p.getHand();
	HandInfo HI;
	int value=getMaxValue(hcards);
	HI.v_=value;

	if( isRoyalFlush(hcards))
	{
		HI.h_=royalflush;
		return HI;
	}
	if( isStraightFlush(hcards))
	{
		HI.h_=straightflush;
		return HI;
	}
	if( isFlush(hcards))
	{
		HI.h_=hflush;
		return HI;
	}
	if( isStraight(hcards))
	{
		HI.h_=straight;
		return HI;
	}
	if( isFourOfAKind(hcards))
	{
		HI.h_=fourofakind;
		return HI;
	}
	if( isFullHouse(hcards))
	{
		HI.h_=fullhouse;
		return HI;
	}
	if( isThreeOfAKind(hcards))
	{
		HI.h_=threeofakind;
		return HI;
	}
	if( isTwoPair(hcards))
	{
		HI.h_=twopair;
		return HI;
	}
	if( isOnePair(hcards))
	{
		HI.h_=onepair;
		return HI;
	}
	HI.h_=sigle;
	return HI;
}

int Game::getMaxValue(vector<Card*>& vc)
{
	vector<Card*>::iterator iter=vc.begin();
	int maxvalue=0;
	for(; iter!=vc.end(); ++iter)
	{
		if((*iter)->getSuitValue()==1)
			return 1;
		if( (*iter)->getSuitValue()>maxvalue )
			maxvalue=(*iter)->getSuitValue();
	}
	return maxvalue;
}
int Game::getMinValue(vector<Card*>& vc)
{
	vector<Card*>::iterator iter=vc.begin();
	int minvalue=13;
	for(; iter!=vc.end(); ++iter)
	{
		if( (*iter)->getSuitValue()==1)
			continue;
		if( (*iter)->getSuitValue()<minvalue )
			minvalue=(*iter)->getSuitValue();
	}
	return minvalue;
}

bool Game::isRoyalFlush(vector<Card*>& vc)
{
	return	isStraightFlush(vc) && 
			getMinValue(vc)!=10 &&
			getMaxValue(vc)!=1 ;
}

bool Game::isStraightFlush(vector<Card*>& vc)
{
	return isFlush(vc) && isStraight(vc);
}

bool Game::isFlush(vector<Card*>& vc)
{
	if(vc.size()<1)
		return false;

	vector<Card*>::iterator iter=vc.begin();
	Suit lastSuit=(*iter)->getSuit();
	for(; iter!=vc.end(); ++iter)
	{
		if( (*iter)->getSuit()!= lastSuit)
			return false;
	}	
	return true;
}

bool Game::isStraight(vector<Card*>& vc)
{
	vector<int> value;
	vector<Card*>::iterator iter=vc.begin();
	for (; iter!=vc.end(); ++iter)
	{
		value.push_back((*iter)->getSuitValue());
	}
	sort(value.begin(),value.end());
	
	if(value.size()!=5 )
		return false;
	if( (value.front()==1) && (value.back()==13) ) //has Ace and King
	{
		if( (find(value.begin(),value.end(),10)==value.end()) ||
			(find(value.begin(),value.end(),11)==value.end()) ||
			(find(value.begin(),value.end(),12)==value.end()) )
		return false;
	}
	else//no Ace
	{
		vector<int>::iterator int_iter=value.begin();
		for(; int_iter!=value.end(); ++int_iter)
		{
			if( count(value.begin(),value.end(),*int_iter)>1)
				return false;
		}
		if( value.back()- value.front()!=4)
			return false;
	}
	return true;
}
bool Game::isFourOfAKind(vector<Card*>& vc)
{
	vector<int> value;
	vector<Card*>::iterator iter=vc.begin();
	for (; iter!=vc.end(); ++iter)
	{
		value.push_back((*iter)->getSuitValue());
	}
	sort(value.begin(),value.end());

	vector<int>::iterator int_iter=value.begin();
	for(; int_iter!=value.end(); ++int_iter)
	{
		if(count(value.begin(),value.end(),*int_iter)==4)
			return true;
	}
	return false;
}
bool Game::isFullHouse(vector<Card*>& vc)
{
	return isOnePair(vc) && isThreeOfAKind(vc);
}

bool Game::isThreeOfAKind(vector<Card*>& vc)
{
	vector<int> value;
	vector<Card*>::iterator iter=vc.begin();
	for (; iter!=vc.end(); ++iter)
	{
		value.push_back((*iter)->getSuitValue());
	}
	sort(value.begin(),value.end());

	vector<int>::iterator int_iter=value.begin();
	for(; int_iter!=value.end(); ++int_iter)
	{
		if(count(value.begin(),value.end(),*int_iter)==3)
			return true;
	}
return false;
}
bool Game::isTwoPair(vector<Card*>& vc)
{
	int condition=0;
	vector<int> value;
	vector<Card*>::iterator iter=vc.begin();
	for (; iter!=vc.end(); ++iter)
	{
		value.push_back((*iter)->getSuitValue());
	}
	sort(value.begin(),value.end());

	vector<int>::iterator int_iter=value.begin();
	for(; int_iter!=value.end(); ++int_iter)
	{
		if(count(value.begin(),value.end(),*int_iter)==2)
			condition++;
	}
	if(condition==4)
		return true;
	return false;
}
bool Game::isOnePair(vector<Card*>& vc)
{
	int condition=0;
	vector<int> value;
	vector<Card*>::iterator iter=vc.begin();
	for (; iter!=vc.end(); ++iter)
	{
		value.push_back((*iter)->getSuitValue());
	}
	sort(value.begin(),value.end());

	vector<int>::iterator int_iter=value.begin();
	for(; int_iter!=value.end(); ++int_iter)
	{
		if(count(value.begin(),value.end(),*int_iter)==2)
			condition++;
	}
	if(condition==2)
		return true;
	return false;
}

void Game::deal()
{
	if(isFinish())
	{
		endRound();
		cout<<"Do u want continue? Y/N"<<endl;
		char c;
		cin>>c;
		if(c=='Y' ||c=='y')
			startRound();
		else
			end();
		return;
	}
	computer_.bid().push_back(pk_.dealOne());
	play_.bid().push_back(pk_.dealOne());
	cardCount_++;
	show();
}

void Game::init()
{
	pk_.init(52);
	play_.init();
	computer_.init();
}

void Game::show()
{
	computerInfo();
	playerInfo();
}

void Game::shuffle()
{
	pk_.shuffle();
}

bool Game::ante(int USD)
{
	if(computer_.getMoney()<USD)
	{
		setWin(true);
		endRound();
	}
	return play_.ante(USD) &&computer_.ante(USD) ;
}

void Game::setWin(bool bw)
{
	play_.setWin(true);
}
void Game::usage()
{
	cout<<"+-------------------------------------------------------------+\n"
		<<"| Welcome to showhand:                                        |\n"
		<<"+-------------------------------------------------------------+\n"
		<<"| There are some valid command list below :                   |\n"
		<<"| bid                                                         |\n"
		<<"| ante [money]                                                |\n"
		<<"| show                                                        |\n"
		<<"| out                                                         |\n"
		<<"+-------------------------------------------------------------+\n"
		<<endl;
}

void Game::computerInfo()
{
	cout<<"+-------------------------------------------------------------+\n"
		<<"| Computer Information:                                       |\n"
		<<"+-------------------------------------------------------------+\n";
	computer_.show();
}

void Game::playerInfo()
{
	cout<<"+-------------------------------------------------------------+\n"
		<<"| your Information:                                           |\n"
		<<"+-------------------------------------------------------------+\n";
	play_.show();
}

void Game::stakeAdd(int USD)
{
	stake_+=USD;
}
